`timescale 1ns / 1ps
`include "defines.vh"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/06/12 11:15:23
// Design Name: 
// Module Name: EX_MEM
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module EX_MEM(
    input [0:0] clk,
    input [0:0] rst,

    input [0:0] Clear_Flag_Input,


    //从ALU接收
    input [`ALU_Parameter_BUS] ALU_Result_Input,
    input [0:0] ALU_Carry_Input,
    input [0:0] ALU_Overflow_Input,

    //从CU接收
    input [0:0] Write_Reg_Flag_Input,
    input [`Reg_Addr_Bus] Write_Reg_Addr_Input,
    
    input [0:0] Write_Reg_from_ALU_Flag_Input,
    input [0:0] Write_Reg_from_CU_Flag_Input,
    input [`Reg_Data_Bus] Write_Reg_from_CU_Data_Input,

    //RAM操作
    input [0:0]  RAM_Access_Flag_Input,
    input [`RAM_Operation_BUS] RAM_Operation_Input,
    input [`RAM_Data_BUS]  RAM_Write_Data_Input,

    ////发送到MEM
    output [`ALU_Parameter_BUS] ALU_Result_Output,
    output [0:0] ALU_Carry_Output,
    output [0:0] ALU_Overflow_Output,



    output [0:0] Write_Reg_Flag_Output,
    output [`Reg_Addr_Bus] Write_Reg_Addr_Output,

    output [0:0] Write_Reg_from_ALU_Flag_Output,
    output [0:0] Write_Reg_from_CU_Flag_Output,
    output [`Reg_Data_Bus] Write_Reg_from_CU_Data_Output,

    //RAM操作
    output [0:0] RAM_Access_Flag_Output,
    output [`RAM_Operation_BUS] RAM_Operation_Output,
    output [`RAM_Data_BUS]  RAM_Write_Data_Output,

    // 数据冒险 前递操作
    // 将写入寄存器标志，写入寄存器地址 ，ALU结果前递给ID_EX
    output [0:0] Write_Reg_Flag_Forward_Output,
    output [`Reg_Addr_Bus] Write_Reg_Addr_Forward_Output,
    output [`ALU_Parameter_BUS] ALU_Result_Forward_Output


    );


    Latch #(32) Latch_EX_MEM_ALU_Result(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`ALU_Rst_Data), 
    .Write_Input(ALU_Result_Input), .Read_Output(ALU_Result_Output));
    
    Latch #(1) Latch_EX_MEM_ALU_Carry(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Zero), 
    .Write_Input(ALU_Carry_Input), .Read_Output(ALU_Carry_Output));
    
    Latch #(1) Latch_EX_MEM_ALU_Overflow(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Zero), 
    .Write_Input(ALU_Overflow_Input), .Read_Output(ALU_Overflow_Output));
    
    Latch #(1) Latch_EX_MEM_Write_Reg_from_ALU_Flag(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Zero), 
    .Write_Input(Write_Reg_from_ALU_Flag_Input), .Read_Output(Write_Reg_from_ALU_Flag_Output));
    
    Latch #(1) Latch_EX_MEM_Write_Reg_from_CU_Flag(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Zero), 
    .Write_Input(Write_Reg_from_CU_Flag_Input), .Read_Output(Write_Reg_from_CU_Flag_Output));
    
    Latch #(32) Latch_EX_MEM_Write_Reg_from_CU_Data(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Regs_Data_Rst), 
    .Write_Input(Write_Reg_from_CU_Data_Input), .Read_Output(Write_Reg_from_CU_Data_Output));

    Latch #(1) Latch_EX_MEM_Write_Reg_Flag(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Write_Reg_Flag_Disabled), 
    .Write_Input(Write_Reg_Flag_Input), .Read_Output(Write_Reg_Flag_Output));
    
    Latch #(5) Latch_EX_MEM_Write_Reg_Addr(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Regs_Addr_Rst), 
    .Write_Input(Write_Reg_Addr_Input), .Read_Output(Write_Reg_Addr_Output));

    Latch #(1) Latch_EX_MEM_RAM_Access_Flag(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`RAM_Access_Flag_Disabled), 
    .Write_Input(RAM_Access_Flag_Input), .Read_Output(RAM_Access_Flag_Output));

    Latch #(4) Latch_EX_MEM_RAM_Operation(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`RAM_NOP), 
    .Write_Input(RAM_Operation_Input), .Read_Output(RAM_Operation_Output));

    Latch #(32) Latch_EX_MEM_RAM_Write_Data(.clk(clk), .rst(rst), .Clear_Flag(Clear_Flag_Input), .Default_Value(`Zero32), 
    .Write_Input(RAM_Write_Data_Input), .Read_Output(RAM_Write_Data_Output));






    // 前递操作: 前递的数据与向后传的数据相同
    assign Write_Reg_Flag_Forward_Output = Write_Reg_Flag_Input;
    assign Write_Reg_Addr_Forward_Output = Write_Reg_Addr_Input;
    assign ALU_Result_Forward_Output = (Write_Reg_from_ALU_Flag_Input ==  `Write_reg_from_ALU_Enabled) ? ALU_Result_Input : `Zero32;







    always @(posedge clk) begin
        $display($time,"=================  EX_MEM:ALU_Result:%d,  Carry:%d,  Overflow:%d,  Write_reg_from_ALU:%d,  Write_Flag:%d,  Write_Addr:%d",$signed(ALU_Result_Output),ALU_Carry_Output,ALU_Overflow_Output,Write_Reg_from_ALU_Flag_Output,Write_Reg_Flag_Output,Write_Reg_Addr_Output);

    end














endmodule
